/****************************************************************************
 *
 *  LinuxChatty
 *  Copyright (C) 2010, David Hsu.
 * 
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 ***************************************************************************/
#ifndef _SCROLLABLEVIEW_H_
#define _SCROLLABLEVIEW_H_

#include "Window.h"
#include "WindowInfo.h"
#include <string>
#include <vector>
#include <map>
#include <stack>

/**
 * ScrollableView
 *
 * Base class that supports the ability to display text on the screen in a
 * scrollable window.
 * Currently, this view can only scroll vertically, no horizontal support yet.
 */
class ScrollableView : public Window
{
public:
	ScrollableView(WindowInfo info);
	
	// Set the text to display
	void SetText(const std::string& text);
	void ClearText();
	
	// Scrolls the text on the display
	void Scroll(const int distance);
	
	// Reveals the currently selected spoiler tag, if any
	void RevealCurrentTag();
	
	// Base functions for updating the screen
	void Refresh();

protected:
    // Parse the comemnts and figure out what to do with special tags, like
    // spoilers.
    void ParseComment(const std::string& comment);
    
    // Formats the comment and replaces any active spoilers with udnerscores
    void SpoilerComment();
        
    // Connect spoiler underscores together so it'll be one big block instead of
    // individual words underlined.
    void FormatTextArray();
    
    // Calculate the starting and ending index of the string currently
    // displayed.
    void CalculateDisplayIndex();
    
    // Finds the previous spoiler tag
    int FindPreviousSpoiler();
    
	// Text array for word wrapped text
	std::vector<std::string> textArray;
	
	// Mapping of spoiler tags to hide from the comments until they are
	// revealed by the user. The first int key is the beginning position of
	// the spoiler tag and the stack of ints are the closing tags. In this way,
	// if there are multiple spoiler tags starting from the same start index,
	// then this will automaticaly reveal the correct layers.
	std::map< unsigned int, std::stack<unsigned int> > spoilerMap;
	
	// Current formatted comment to display. This has the spoilers hidden
	// and revealed spoilers shown. The raw comment is the string without
	// any hidden tags, just pure text used as a reference.
	std::string currentComment;
	std::string rawComment;
	
	// Keeps track of the top most index to make the scrolling correct
	unsigned int topRow;
    
    // Keep track of current spoiler position to show where to highlight
    // the text. This position in the first index and also the key to the map.
    int spoilerPosition;
    
    // Keep track of the current index in the string that is being displayed
    // and the last index in order to determine the selectable spoilers
    unsigned int displayStartIndex, displayEndIndex;
};

#endif
